home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Format 1997 July
/
macformat52.iso
/
mac
/
Shareware Plus
/
Educational
/
LEE 2.1
/
Source
/
body.c
next >
Wrap
Text File
|
1996-08-07
|
26KB
|
1,160 lines
/* body.c
* Copyright (1992)
*
* Rik Belew. University of California, San Diego
* Filippo Menczer. University of California, San Diego
* Greg Linden. University of California, San Diego
*
* This software may be redistributed without charge;
* this notice should be preserved.
*/
#include "defs.h"
#include <math.h>
/* Given a heading, moveDiff() returns the
shift in the current position needed to
take one step in that direction. This
can then be multiplied by a scalar to
do larger moves in that direction. */
position
moveDiff (heading)
int heading;
{
position thePosition;
switch (heading) {
case UP:
thePosition.x = 0;
thePosition.y = 1;
break;
case DOWN:
thePosition.x = 0;
thePosition.y = -1;
break;
case LEFT:
thePosition.x = -1;
thePosition.y = 0;
break;
case RIGHT:
thePosition.x = 1;
thePosition.y = 0;
break;
default:
printf("Error in moveDiff(). Undefined direction.\n");
exit(1);
}
return (thePosition);
}
/* Given the horizontal and vertical
distance to a cell, returns the position of
the new cell from the initial position,
compensating for the toroidal world. */
position
find_cell (coordinates, delta)
position coordinates,delta;
{
position newCell;
newCell.x = coordinates.x;
newCell.y = coordinates.y;
newCell.x+=delta.x;
if (newCell.x<0)
newCell.x+=x_dim;
else if (newCell.x>=x_dim)
newCell.x-=x_dim;
newCell.y+=delta.y;
if (newCell.y<0)
newCell.y+=y_dim;
else if (newCell.y>=y_dim)
newCell.y-=y_dim;
return (newCell);
}
/* range() returns a list of the positions of the cells
that are within range of the given sensor */
listofPositions *
range(org_pos, org_direction, theSensor)
position org_pos;
int org_direction;
sensor theSensor;
{
listofPositions *rangeList=NIL_POINTER, *temp;
position diff;
int direction, size;
register int i;
switch (theSensor.system) {
case CONTACT:
/* Contact sensor */
/* Add the position one move in the heading
direction from the org_pos to the rangeList.
Since the world is torroidal, if the
organism is on an edge of the map, this may
require wrapping around the map to the other
side. */
rangeList = (listofPositions*) malloc (sizeof(listofPositions));
if (rangeList == NIL_POINTER)
{
printf("\nERROR: rangeList malloc\n");
exit(1);
}
rangeList->next = NIL_POINTER;
direction = facing(org_direction, theSensor.orientation);
diff = moveDiff(direction);
rangeList->current = find_cell(org_pos, diff);
break;
case AMBIENT:
/* Ambient sensor */
/* Add the positions around org_pos, depending
on direction of org and orientation of
sensor, to the rangeList.
Since the world is torroidal, if the
organism is on an edge of the map, this may
require wrapping around the map to the other
side. */
size = range_size(theSensor.range);
rangeList = temp = (listofPositions*) malloc(sizeof(listofPositions));
if (rangeList == NIL_POINTER)
{
printf("\nERROR: rangeList malloc\n");
exit(1);
}
for (i=0; i<size-1; i++)
{
diff.x = off_vec[1+facing(org_direction,theSensor.orientation)][i]->x;
diff.y = off_vec[1+facing(org_direction,theSensor.orientation)][i]->y;
temp->current = find_cell(org_pos, diff);
temp->distance = off_vec[1+facing(org_direction,theSensor.orientation)][i]->d;
temp->next = (listofPositions*) malloc(sizeof(listofPositions));
if (temp->next == NIL_POINTER)
{
printf("\nERROR: malloc in range()\n");
exit(1);
}
temp = temp->next;
}
diff.x = off_vec[1+facing(org_direction,theSensor.orientation)][size-1]->x;
diff.y = off_vec[1+facing(org_direction,theSensor.orientation)][size-1]->y;
temp->current = find_cell(org_pos, diff);
temp->distance = off_vec[1+facing(org_direction,theSensor.orientation)][size-1]->d;
temp->next = NIL_POINTER;
break;
default:
printf("\nError: Unknown sensor in range().\n");
exit(1);
}
return(rangeList);
}
/*
* number of cells in range of ambient sensor
*/
int range_size(range)
int range;
{
if (range == 1) return(1);
else return(2*range*range - 4*range + 4);
}
/*
* scales the distance (measured in number of steps)
* before its inverse is used to weigh the signal
* produced by an ambient sensor, eg, so that inputs
* aren't too week on average (flat part of logistic)
*/
float scale(n)
int n;
{
/*
* weight large for n=1 (scale slope > 1)
* weight flat for n>1 (scale slope < 1)
* 2.5 is needed to avoid division by 0
* (any number > log(.1) works the same
* given the subsequent normalization...)
* 0.9 is needed to get slope > 1 for n=1
* (any number s.t. 0 < number < 1 works)
*
return ((float)n);
return ((float)log((double)(n + 1)));
*/
return (2.5 + (float)log((double)n - 0.9));
}
/*
* loads the global offset array off_vec for ambient sensors
* and norm_dist[] for normalization (sum of distances).
* NOTE 1: following Greg's convention, UP <=> y increasing
* NOTE 2: since facing() returns absolute direction of sensor
* field and not org facing direction, we decided that
* distance is relative to sensor absolute orientation:
* it doesn't count minimal number of steps, but
* rather ditance from sensor "location" (defined
* as absolute orientation).
*/
void carica_offsets(range)
int range;
{
int r;
register int i,j;
if (range == 1)
{
off_vec[0][0]->x = -1;
off_vec[0][0]->y = 0;
off_vec[0][0]->d = scale(range);
off_vec[1][0]->x = 0;
off_vec[1][0]->y = 1;
off_vec[1][0]->d = scale(range);
off_vec[2][0]->x = 1;
off_vec[2][0]->y = 0;
off_vec[2][0]->d = scale(range);
off_vec[3][0]->x = 0;
off_vec[3][0]->y = -1;
off_vec[3][0]->d = scale(range);
r = range_size(range);
for (i=0; i<r; i++) norm_dist[range-1] += 1.0/off_vec[0][i]->d;
}
else if (range == 2)
{
carica_offsets(1);
off_vec[0][1]->x = -2;
off_vec[0][1]->y = 0;
off_vec[0][1]->d = scale(range);
off_vec[1][1]->x = 0;
off_vec[1][1]->y = 2;
off_vec[1][1]->d = scale(range);
off_vec[2][1]->x = 2;
off_vec[2][1]->y = 0;
off_vec[2][1]->d = scale(range);
off_vec[3][1]->x = 0;
off_vec[3][1]->y = -2;
off_vec[3][1]->d = scale(range);
off_vec[0][2]->x = 0;
off_vec[0][2]->y = -1;
off_vec[0][2]->d = scale(range);
off_vec[1][2]->x = -1;
off_vec[1][2]->y = 0;
off_vec[1][2]->d = scale(range);
off_vec[2][2]->x = 0;
off_vec[2][2]->y = 1;
off_vec[2][2]->d = scale(range);
off_vec[3][2]->x = 1;
off_vec[3][2]->y = 0;
off_vec[3][2]->d = scale(range);
off_vec[0][3]->x = 0;
off_vec[0][3]->y = 1;
off_vec[0][3]->d = scale(range);
off_vec[1][3]->x = 1;
off_vec[1][3]->y = 0;
off_vec[1][3]->d = scale(range);
off_vec[2][3]->x = 0;
off_vec[2][3]->y = -1;
off_vec[2][3]->d = scale(range);
off_vec[3][3]->x = -1;
off_vec[3][3]->y = 0;
off_vec[3][3]->d = scale(range);
r = range_size(range);
for (i=0; i<r; i++) norm_dist[range-1] += 1.0/off_vec[0][i]->d;
}
else
{
carica_offsets(range-1);
r = range_size(range-1);
off_vec[0][r]->x = -range;
off_vec[0][r]->y = 0;
off_vec[0][r]->d = scale(range);
off_vec[1][r]->x = 0;
off_vec[1][r]->y = range;
off_vec[1][r]->d = scale(range);
off_vec[2][r]->x = range;
off_vec[2][r]->y = 0;
off_vec[2][r]->d = scale(range);
off_vec[3][r]->x = 0;
off_vec[3][r]->y = -range;
off_vec[3][r]->d = scale(range);
r++;
off_vec[0][r]->x = range-2;
off_vec[0][r]->y = 0;
off_vec[0][r]->d = scale(range);
off_vec[1][r]->x = 0;
off_vec[1][r]->y = 2-range;
off_vec[1][r]->d = scale(range);
off_vec[2][r]->x = 2-range;
off_vec[2][r]->y = 0;
off_vec[2][r]->d = scale(range);
off_vec[3][r]->x = 0;
off_vec[3][r]->y = range-2;
off_vec[3][r]->d = scale(range);
for (i=1, j=3-range; i<=range-3; i++, j++)
{
r++;
off_vec[0][r]->x = -j;
off_vec[0][r]->y = -i;
off_vec[0][r]->d = scale(range);
off_vec[1][r]->x = -i;
off_vec[1][r]->y = j;
off_vec[1][r]->d = scale(range);
off_vec[2][r]->x = j;
off_vec[2][r]->y = i;
off_vec[2][r]->d = scale(range);
off_vec[3][r]->x = i;
off_vec[3][r]->y = -j;
off_vec[3][r]->d = scale(range);
r++;
off_vec[0][r]->x = -j;
off_vec[0][r]->y = i;
off_vec[0][r]->d = scale(range);
off_vec[1][r]->x = i;
off_vec[1][r]->y = j;
off_vec[1][r]->d = scale(range);
off_vec[2][r]->x = j;
off_vec[2][r]->y = -i;
off_vec[2][r]->d = scale(range);
off_vec[3][r]->x = -i;
off_vec[3][r]->y = -j;
off_vec[3][r]->d = scale(range);
}
for (i=1, j=range-2; i<=range-1; i++, j--)
{
r++;
off_vec[0][r]->x = -j;
off_vec[0][r]->y = -i;
off_vec[0][r]->d = scale(range);
off_vec[1][r]->x = -i;
off_vec[1][r]->y = j;
off_vec[1][r]->d = scale(range);
off_vec[2][r]->x = j;
off_vec[2][r]->y = i;
off_vec[2][r]->d = scale(range);
off_vec[3][r]->x = i;
off_vec[3][r]->y = -j;
off_vec[3][r]->d = scale(range);
r++;
off_vec[0][r]->x = -j;
off_vec[0][r]->y = i;
off_vec[0][r]->d = scale(range);
off_vec[1][r]->x = i;
off_vec[1][r]->y = j;
off_vec[1][r]->d = scale(range);
off_vec[2][r]->x = j;
off_vec[2][r]->y = -i;
off_vec[2][r]->d = scale(range);
off_vec[3][r]->x = -i;
off_vec[3][r]->y = -j;
off_vec[3][r]->d = scale(range);
}
r = range_size(range);
for (i=0; i<r; i++) norm_dist[range-1] += 1.0/off_vec[0][i]->d;
}
}
void
killListOfPos (list_pointer)
listofPositions *list_pointer;
{
listofPositions *thePtr = list_pointer, *oldPtr;
oldPtr = thePtr;
while (thePtr!=NIL_POINTER) {
thePtr = thePtr->next;
free((char *) oldPtr);
oldPtr = thePtr;
}
}
/* check_world() returns a list of the cells that
contain atoms that can be sensed by the given
sensor of the organism.
Thanks to Federico Cecconi and Virginia Games.
*/
listofPositions*
check_world (org_pos, org_direction, theSensor)
position org_pos;
int org_direction;
sensor theSensor;
{
listofPositions *sensedCells=NIL_POINTER, *rangeList, *temp, *p;
cell *cellPointer;
boolean detectable=FALSE;
switch (theSensor.system) {
case CONTACT:
rangeList = range (org_pos, org_direction, theSensor);
/*********************
for (each item in rangeList) {
Check if sensor can detect atoms at
position. If not or position
empty, delete from rangeList.
}
********************/
detectable=FALSE;
if (rangeList==NIL_POINTER) {
printf("NIL returned by range().\n");
exit(1);
}
else {
cellPointer = world[rangeList->current.x][rangeList->current.y];
while ((cellPointer!=NIL_POINTER) && (!detectable)){
if (cellPointer->type == food)
if (theSensor.complex[cellPointer->datum.atom]!=0)
detectable=TRUE;
cellPointer=cellPointer->next;
}
if (detectable)
sensedCells = rangeList;
else
killListOfPos(rangeList);
}
break;
case AMBIENT:
sensedCells = rangeList = temp = range (org_pos, org_direction, theSensor);
if (rangeList==NIL_POINTER) {
printf("NIL returned by range().\n");
exit(1);
}
else
{
while (rangeList!=NIL_POINTER)
{
detectable=FALSE;
cellPointer = world[rangeList->current.x][rangeList->current.y];
while ((cellPointer!=NIL_POINTER) && (!detectable))
{
if (cellPointer->type == food)
if (theSensor.complex[cellPointer->datum.atom]!=0)
detectable=TRUE;
cellPointer=cellPointer->next;
}
if (temp == rangeList)
{
rangeList = rangeList->next;
if (!detectable)
{
/* killListOfPos(temp); */
p = temp;
free(p);
sensedCells = temp = rangeList;
}
}
else
{
if (!detectable)
{
rangeList = rangeList->next;
/* killListOfPos(temp->next); */
p = temp->next;
free(p);
temp->next = rangeList;
}
else
{
temp = rangeList;
rangeList = rangeList->next;
}
}
}
}
break;
default:
printf("\nError: Unknown sensor type in check_world();.\n");
exit(1);
}
return (sensedCells);
}
/* Modifies the activity level of the input nodes of
the neural network on the appropriate sensor
according to what the sensor has detected.
Thanks to Federico Cecconi and Virginia Games.
*/
void
sense (org_pos, org_direction, theSensor, theGut, activity_levels)
position org_pos;
int org_direction;
sensor theSensor;
int theGut[]; /* error if used constant MAXTYPES for dimension */
float *activity_levels;
{
listofPositions *sensedCells=NIL_POINTER, *rangeList=NIL_POINTER;
float trigger = 0.0;
cell *cellPointer = NIL_POINTER;
int counter;
boolean maskCheck=FALSE;
boolean detectedYet[MAXTYPES];
/* Get the level of firing of the input for the sensor
(assumes only one input node currently) */
switch (theSensor.system) {
case GUT_SENSOR:
for (counter=0; counter<types;counter++)
if (theGut[counter]>0)
trigger += theSensor.complex[counter];
break;
case CONTACT:
for (counter=0;counter<types; counter++) detectedYet[counter] = FALSE;
sensedCells = check_world (org_pos, org_direction, theSensor);
rangeList = sensedCells;
if (sensedCells!=NIL_POINTER) {
/* Add levels of triggering of the sensor.
Only detect presense
of atoms, not number. */
cellPointer = world[sensedCells->current.x][sensedCells->current.y];
while (cellPointer!=NIL_POINTER) {
if (cellPointer->type == food)
if (!detectedYet[cellPointer->datum.atom]) {
trigger+=theSensor.complex[cellPointer->datum.atom];
detectedYet[cellPointer->datum.atom]=TRUE;
}
cellPointer = cellPointer->next;
}
}
break;
case AMBIENT:
sensedCells = check_world (org_pos, org_direction, theSensor);
rangeList = sensedCells;
while (sensedCells!=NIL_POINTER) {
for (counter=0;counter<types; counter++) detectedYet[counter] = FALSE;
cellPointer = world[sensedCells->current.x][sensedCells->current.y];
while (cellPointer!=NIL_POINTER) {
if (cellPointer->type == food)
if (!detectedYet[cellPointer->datum.atom]) {
trigger+=(theSensor.complex[cellPointer->datum.atom]/sensedCells->distance);
detectedYet[cellPointer->datum.atom]=TRUE;
}
cellPointer = cellPointer->next;
}
sensedCells = sensedCells->next;
}
break;
default:
printf("Error: Unknown sensor type.\n");
exit(1);
}
/* Normalize the trigger level to 1 and max out at 1.
Place the final firing value for the input node in
an array that represents the input nodes of the
neural network. */
switch (theSensor.system) {
case AMBIENT:
trigger/=norm_dist[theSensor.range];
case GUT_SENSOR:
case CONTACT:
trigger/=COMPLEX_SIZE;
for (counter=0; counter<(*layer_descp);counter++)
if (theSensor.mask[counter]!=0) {
activity_levels[counter] = trigger;
if (maskCheck) {
printf("\nSensor masking to more than one input!\nCode is not designed for this.\n");
exit(1);
}
else
maskCheck = TRUE;
}
break;
default:
printf("Error: Unknown sensor type.\n");
exit(1);
}
/* killListOfPos(sensedCells); */
killListOfPos(rangeList);
}
/* Sense the world using all the sensors (which place
their firing levels for their input nodes in a temporary
array), combine all their inputs, and place
the combined input to the network in the network. */
void
sense_world (organism)
struct indiv *organism;
{
int x,y;
float *new_levels, *activity_levels;
position org_pos;
int numInputs = (*layer_descp);
org_pos.x=organism->worldx;
org_pos.y=organism->worldy;
activity_levels = (float *) malloc(NINPUTS * sizeof(float));
new_levels = (float *) malloc(NINPUTS * sizeof(float));
if ((activity_levels == NIL_POINTER) || (new_levels == NIL_POINTER))
{
printf("\nERROR: levels malloc\n");
exit(1);
}
for (x=0; x<numInputs; x++)
*(activity_levels + x) = 0;
/* Total the values that the individual sensors will
place on the inputs of the neural net */
for (x=0; x<nsensors; x++) {
for (y=0; y<numInputs; y++)
*(new_levels + y) = 0;
sense(org_pos, organism->direction, organism->sensor_specs[x], organism->gut, new_levels);
for (y=0;y<numInputs; y++)
activity_levels[y]+=new_levels[y];
}
/* Put activity_levels vector as values on inputs of neural network */
for (x=0; x<numInputs; x++)
*(*(organism->layerp)+x) = activity_levels[x];
free((char *) activity_levels);
free((char *) new_levels);
}
/* Given the direction of the organism and the
location of the sensor/motor, calculates the
absolute facing of that unit. This can then
be used to determine the direction of
movement/sensing. */
int
facing (org_direction, object_loc)
int org_direction, object_loc;
{
int heading;
switch (object_loc) {
case BACKWARD:
switch (org_direction) {
case UP:
heading = DOWN;
break;
case DOWN:
heading = UP;
break;
case LEFT:
heading = RIGHT;
break;
case RIGHT:
heading = LEFT;
break;
default:
printf("Error in facing(). Undefined direction.\n");
exit(1);
}
break;
case LEFT_SIDE:
switch (org_direction) {
case UP:
heading = LEFT;
break;
case DOWN:
heading = RIGHT;
break;
case LEFT:
heading = DOWN;
break;
case RIGHT:
heading = UP;
break;
default:
printf("Error in facing(). Undefined direction.\n");
exit(1);
}
break;
case RIGHT_SIDE:
switch (org_direction) {
case UP:
heading = RIGHT;
break;
case DOWN:
heading = LEFT;
break;
case LEFT:
heading = UP;
break;
case RIGHT:
heading = DOWN;
break;
default:
printf("Error in facing(). Undefined direction.\n");
exit(1);
}
break;
case FORWARD:
heading = org_direction;
break;
default:
printf("Error in facing(). Undefined location.\n");
exit(1);
}
return (heading);
}
/* Returns the change in position that a jump motor
produces */
position
jumpMotorMove (outputLayer, numOutputs, theMotor, newFacing)
float* outputLayer;
int numOutputs;
motor theMotor;
int *newFacing; /* Pass by location */
{
position diff;
int org_direction = *newFacing;
int index, dist;
diff.x = 0;
diff.y = 0;
/* A jump motor is based off one continuous value. */
for (index=0; index<numOutputs;index++)
if (theMotor.mask[index]==1) {
dist = (int)((*(outputLayer+index)) * (float)theMotor.power);
break;
}
diff = moveDiff(org_direction);
diff.x *= dist;
diff.y *= dist;
/* ADD LOCATION OF MOTOR HERE! */
if (rans(1.0) > 0.0)
{
if (rans(1.0) > 0.0)
*newFacing = facing (org_direction, RIGHT_SIDE);
else
*newFacing = facing (org_direction, LEFT_SIDE);
}
return (diff);
}
/* Returns the change in position that a binary motor
produces */
position
binaryMotorMove (outputLayer, numOutputs, theMotor, newFacing)
float* outputLayer;
int numOutputs;
motor theMotor;
int *newFacing; /* Pass by location */
{
position diff;
int org_direction = *newFacing;
int command=0, index, bin_val=2;
diff.x = 0;
diff.y = 0;
/* A binary motor is based off two bit values.
The masked values must be converted. Anything
above .5 will be considered 1 */
for (index=0; index<numOutputs;index++)
if (theMotor.mask[index]==1) {
if (*(outputLayer+index)>.5) {
command+=bin_val;
}
bin_val/=2;
if (bin_val<1)
bin_val = 0;
}
switch (command) {
case 0:
break;
case 1:
*newFacing = facing (org_direction, RIGHT_SIDE);
break;
case 2:
*newFacing = facing (org_direction, LEFT_SIDE);
break;
case 3:
/* ADD LOCATION OF MOTOR HERE! */
diff = moveDiff(org_direction);
diff.x *= theMotor.power;
diff.y *= theMotor.power;
break;
}
return (diff);
}
/* Move the organism as indicated by the neural
network */
void move (organism)
struct indiv *organism;
{
int counter;
position org_pos, posDiff, tempDiff, new_pos;
int newFacing = organism->direction;
boolean isSelected=FALSE, isFound = FALSE;
cell *theCell;
int orgItemNum = 0;
org_pos.x=organism->worldx;
org_pos.y=organism->worldy;
posDiff.x = 0;
posDiff.y = 0;
theCell = world[org_pos.x][org_pos.y];
while ((theCell->next!=NULL) && (!isFound)) {
if ((theCell->type==org) && (theCell->datum.ap==organism))
isFound = TRUE;
else {
theCell = theCell->next;
orgItemNum++;
}
}
if ((theCell->type!=org) || (theCell->datum.ap!=organism)) {
printf("Couldn't find the organism in the cell!\n");
exit(1);
}
/* Motor movements are additive to form
total movement */
for (counter=0; counter<nmotors; counter++) {
switch (organism->motor_specs[counter].system) {
case BINARY:
tempDiff = binaryMotorMove(*(organism->layerp+nlayers-1),
(*(layer_descp+nlayers-1)),
organism->motor_specs[counter],
&newFacing);
posDiff.x += tempDiff.x;
posDiff.y += tempDiff.y;
organism->energy -= ENERGY_USE;
break;
case JUMP:
tempDiff = jumpMotorMove(*(organism->layerp+nlayers-1),
(*(layer_descp+nlayers-1)),
organism->motor_specs[counter],
&newFacing);
posDiff.x += tempDiff.x;
posDiff.y += tempDiff.y;
organism->energy -= ENERGY_USE;
break;
default:
printf("Unknown motor type!");
exit(1);
}
}
new_pos = find_cell(org_pos, posDiff);
if ((new_pos.x!=organism->worldx) || (new_pos.y!=organism->worldy)) {
moveInteractiveLasso(orgItemNum, &isSelected, organism);
del_org(organism);
organism->worldx = new_pos.x;
organism->worldy = new_pos.y;
organism->direction = newFacing;
ins_org(organism);
moveInteractDrawSelectFrame(isSelected, new_pos);
}
else
organism->direction = newFacing;
}
/* Given two cells, computes the horizontal
and vertical distance between them,
compensating for the toroidal world. */
position distance (initCell,finalCell)
position initCell, finalCell;
{
position diff;
int deltaX, deltaY;
deltaX = finalCell.x - initCell.x;
deltaY = finalCell.y - initCell.y;
if (initCell.x<finalCell.x) {
if (deltaX>abs(deltaX - x_dim)) {
deltaX -= x_dim;
}
}
else {
if (abs(deltaX)>(deltaX+x_dim)) {
deltaX += x_dim;
}
}
if (initCell.y<finalCell.y) {
if (deltaY>abs(deltaY - y_dim)) {
deltaY -= y_dim;
}
}
else {
if (abs(deltaY)>(deltaY+y_dim)) {
deltaY += y_dim;
}
}
diff.x = deltaX;
diff.y = deltaY;
return(diff);
}
/*
* called in populati.c;
* returns the number of input units allocated to the sensor
*/
sensor_size(system)
int system;
{
switch(system)
{
case GUT_SENSOR:
case AMBIENT:
case CONTACT:
return(1);
break;
default:
printf("error: sensor system unknown\n");
exit(1);
}
}
/*
* called in populati.c;
* returns the number of output units allocated to the motor
*/
motor_size(system)
int system;
{
switch(system)
{
case BINARY:
return(2);
break;
case JUMP:
return(1);
break;
default: printf("error: motor system unknown\n");
exit(1);
}
}
/*
* called in populati.c;
* returns a sensor/motor mask for new individuals
*/
int get_mask(count, size, i)
int count; /* end unit for this mask */
int size; /* number of units for this mask */
int i; /* unit position */
{
if ((i < count) && (i >= (count - size))) return(1);
else return(0);
}
/*
* called in populati.c;
* returns a motor power for new individuals
*/
int motor_power(system)
int system;
{
switch(system)
{
case BINARY:
return(BIN_POWER);
case JUMP:
return(JUMP_POWER);
default:
printf("Error in motor_power(). Undefined sensor type.\n");
exit(1);
}
}
/*
* called by mutate() in populati.c;
* mutates sensors' complexes and motors' powers
* for new individuals:
* sensitivity in the sensor complex is shifted
* from one atom to another, and the motor power
* is added a random integer in [-1,+1] while
* kept >= 0;
* ATTENTION: for now, orientation and position
* of sensors and motors are not mutated
*/
mu_sensorymotor(ap)
struct indiv *ap;
{
int i,j;
if ((0.5 + rans(0.5)) < MU_SENSOR_PROB)
for (i=0; i<nsensors; i++)
{
do {
j = mrand(types);
} while (ap->sensor_specs[i].complex[j] == 0);
--ap->sensor_specs[i].complex[j];
++ap->sensor_specs[i].complex[mrand(types)];
}
if ((0.5 + rans(0.5)) < MU_MOTOR_PROB)
for (i=0; i<nmotors; i++)
{
ap->motor_specs[i].power += (mrand(3) -1);
while (ap->motor_specs[i].power < 0)
++ap->motor_specs[i].power;
}
}